package com.iussoft.receiveData.schedul;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apache.cache.util.Validator;
import com.apache.tools.StrUtil;
import com.iussoft.tools.LoggerUtil;
import com.iussoft.tools.SpringContextLoader;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;

import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.*;

/**
 * 定时任务后台管理动态配置实现
 */
@Component
public class ScheduledDynamicTask {

    private ThreadPoolTaskScheduler scheduExec;
    private Map<String, ScheduledFuture> threadMap = new HashMap<String, ScheduledFuture>();
    private static final String SCHEDULE_TASK_CACHE="future_task_keys";
    private ExecutorService sendTask;

    public ScheduledDynamicTask(){
        scheduExec = new ThreadPoolTaskScheduler();
        scheduExec.initialize();
        scheduExec.setPoolSize(10);
        sendTask = Executors.newFixedThreadPool(4);
    }

    public void submit(Runnable task){
        scheduExec.submit(task);
    }

    public void submitLog(Runnable task){
        sendTask.submit(task);
    }

    public void submitRun(Runnable task){
        scheduExec.submit(task);
    }

    public Future<T> sbumit(Callable<T> task){
        Future<T> futre = scheduExec.submit(task);
        return futre;
    }

    public static ScheduledDynamicTask getInstance(){
        try {
            Object obj = SpringContextLoader.getBean("scheduledDynamicTask");
            if (obj != null) {
                return (ScheduledDynamicTask) obj;
            }
        }catch (Exception e){}
        return null;
    }

    /**
     * 开始定时任务
     */
    public boolean startTask(JSONObject obj,Runnable runnable,Jedis jedis){
        if(null == obj || obj.isEmpty() || Validator.isNull(obj.getString("taskId")) || Validator.isNull(obj.getString("taskCorn"))){
            return false;
        }
        try {
            String taskId = obj.getString("taskId");
            if(threadMap.containsKey(taskId)){//如果存在此任务，先停掉此任务
                ScheduledFuture sf = threadMap.get(taskId);
                sf.cancel(true);
                threadMap.remove(taskId);
            }
            Trigger trigger = new CustomTrigger(obj.getString("taskCorn"));
            ScheduledFuture sf = scheduExec.schedule(runnable, trigger);
            threadMap.put(taskId, sf);
            jedis.hset(SCHEDULE_TASK_CACHE,taskId,obj.toJSONString());
            return true;
        }catch (RuntimeException e){
            e.printStackTrace();
            LoggerUtil.error("启动定时["+obj.getString("taskId")+"]失败");
            return false;
        }
    }

    /**
     * 结束定时任务
     */
    public boolean stopTask(String taskId,Jedis jedis) {
        if(threadMap.containsKey(taskId)){
            ScheduledFuture sf = threadMap.get(taskId);
            sf.cancel(true);
            threadMap.remove(taskId);
            jedis.hdel(SCHEDULE_TASK_CACHE,taskId);
            return true;
        }
        return false;
    }

    public JSONArray getTaskIds(Jedis jedis){
        JSONArray json = new JSONArray();
        for(String key:threadMap.keySet()){
            JSONObject obj = new JSONObject();
            obj.put(key,jedis.hget(SCHEDULE_TASK_CACHE,key));
            json.add(obj);
        }
        return json;
    }

    public Set<String> getTaskIds(){
       return threadMap.keySet();
    }

    public JSONObject getTaskById(String taskId,Jedis jedis){
        String str = jedis.hget(SCHEDULE_TASK_CACHE,taskId);
        if(StrUtil.isNotNull(str))
            return JSON.parseObject(str);
        return null;
    }

    /**
     * 启动缓存中的定时任务
     */
    public void startTaskList(Jedis jedis){
        Map<String,String> tasks = jedis.hgetAll(SCHEDULE_TASK_CACHE);
        if(null != tasks && !tasks.isEmpty()){
            for(String key:tasks.keySet()){
                JSONObject val = JSON.parseObject(tasks.get(key));
                try {
                    String className = val.getString("className");
                    Class<?> classType = Class.forName(className);
                    //参数类型数组
                    Class[] parameterTypes = {String.class};
                    //参数数组
                    Object[] parameters = {tasks.get(key)};
                    //根据参数类型获取相应的构造函数
                    Constructor constructor = classType.getConstructor(parameterTypes);
                    Runnable call = (Runnable) constructor.newInstance(parameters);
                    startTask(val,call,jedis);
                }catch (Exception e){
                    LoggerUtil.error("启动定时任务["+val.getString("taskId")+"]失败；",e);
                }
            }
        }
    }
}
